#ifndef CHECK_H
#define CHECK_H
#include <QString>
#include <pcl/registration/icp.h>
#include <pcl/common/angles.h>
#include "component.h"
#include "math.h"

using namespace std;
using namespace pcl;

/**
 * @brief enum Representing all the possible controls
 *
 */
enum CheckType { PRESENCE, POSITION, INCLINATION, ORIENTATION, COLOR, HEIGHT, RADIUS };

/**
 * @brief Class representing a check to perform
 * @author Alberto Basso, Luca Tumelero
 * @file check.h
 */
class Check
{
public:
/**
 * @brief Empty costructor
 */
    Check();
/**
 * @brief Full costructor
 * @param componentName_ Name of the component
 * @param type_ Type of control
 * @param thresholdValue_ Value of threshold for the check
 */
    Check(QString componentName_, CheckType type_, float thresholdValue_);
    /**
     * @brief Distructor
     */
    virtual ~Check() {}

    /**
     * @brief Get the component name
     * @return QString Return component name
     */
    QString getComponentName();
    /**
     * @brief Get the type of the check
     * @return CheckType Return the type of the check
     */
    CheckType getType();
    /**
     * @brief Get the threshold for the check
     * @return float Return the threshold set for the check
     */
    float getThresholdValue();
    /**
     * @brief Return the transformation matrix between source component and target component
     * @param[in] sourceComponent Source component
     * @param[in] targetComponent Target coponent
     * @return Eigen::Matrix4f Matrix of the transformation for registrate source to target
     */
    Eigen::Matrix4f getTransformation(Component* sourceComponent, Component* targetComponent);
    /**
     * @brief Return the transformation matrix between source component and target component
     *
     * @param[in] sourceComponent Source component
     * @param[in] targetComponent Target coponent
     * @param[out] testCloud Registered cloud
     * @return Eigen::Matrix4f Matrix of the transformation to register source to target.
     */
    Eigen::Matrix4f getTransformation(Component* sourceComponent, Component* targetComponent, PointCloud<PointXYZRGB>::Ptr testCloud);
    /**
     * @brief Check if the source component is consistent with the target one
     *
     * @param[in] source Source component
     * @param[in] target Target component
     * @param[in] threshold Threshold for the check
     * @return bool Result of the check
     */
    static bool presenceCorrect(Component source, Component target, float threshold);

    /**
     * @brief
     *
     * @param[in] source Source component
     * @param[in] target Target component
     * @param[in] threshold Threshold for the check
     * @return bool Result of the check
     */
    static bool positionCorrect(Component source, Component target, float threshold);

    /**
     * @brief
     *
     * @param[in] transformation Tranformation to put the Source component on the Target one
     * @param[in] threshold Threshold for the check
     * @return bool Result of the check
     */
    static bool inclinationCorrect(Eigen::Matrix4f transformation, float threshold);

    /**
     * @brief
     *
     * @param[in] transformation Tranformation to put the Source component on the Target one
     * @param[in] threshold Threshold for the check
     * @return bool Result of the check
     */
    static bool orientationCorrect(Eigen::Matrix4f transformation, float threshold);

protected:
    QString componentName;
    QString secondComponentName;
    CheckType type;
    float thresholdValue;
    Eigen::Matrix4f transformation;
};

#endif // CHECK_H
